Android系统启动流程(1)

您所在的位置:网站首页 升级Android14 重新修补init_boot文件就行 Android系统启动流程(1)

Android系统启动流程(1)

2024-07-14 13:38| 来源: 网络整理| 查看: 265

前言

        本系列文章简要介绍 Android 系统启动的流程,不会拘泥于源码细节,旨在让读者了解大概的流程。另外,需要提醒大家注意的一点是,阅读本章需要有一定的 C/C++基础,在这个流程中会涉及到很多重要的知识点,这个系列我们就来一一讲解它们,这一篇我们就来学习init进程,本系列文章都将基于Android8.1源码来分析Android系统的启动流程。

init 进程启动过程

       init进程是Android系统中用户空间的第一个进程,进程号为1,是Android系统启动流程中的一个关键的步骤,作为第一个进程,它被赋予了很多极其重要的工作职责,比如创建Zygote(孵化器)和属性服务等。init进程是由多个源文件共同组成的,这些源文件位于源码目录system/core/init中。

    1 引入init 进程

      为了讲解 init 进程,首先要了解 Android 系统启动流程的前几步,以引入 init 进程。

      1. 启动电源以及系统启动        当电源键按下时,引导 芯片代码从预定义的地方(固化在 ROM  )开始执行。加载引导程序 BootLoader 到队 中,然后执行。        2. 引导程序 Bootloader        引导程序 BootLoader 是在 Android 操作系统开始运行前的一 个小 程序,它的主要作用是把操作系统 拉起来并运行。        3. Linux 内核启动        当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。在内核完成系统设 置后,它首 先在系统文件中寻找 init.rc 文件,并启动 init 进程。        4 . init 进程启动        init 进程做的工作比较多 ,主 要用来初始化和启动属性服务和启动 z ygote 进程。           从上面的步骤可以看 出, 当我们按下电源键时, 引导 芯片会加载运行引导程序, 引导 程序又启动 Linux 内核,在 Linux内核 加载 完成后,第一件事就是要启动 init 进程。      2 init 进程的入口函数

       在Linux内核加载完成之后,它首先在系统文件中寻找init.rc文件,并启动init进程,然后查看init进程的入口函数main,代码如下所示:

system/core/init/init.cpp

int main(int argc, char** argv) { // ... 1 if (!strcmp(basename(argv[0]), "ueventd")) { return ueventd_main(argc, argv); } // ... 2 if (!strcmp(basename(argv[0]), "watchdogd")) { return watchdogd_main(argc, argv); } // ... 3 if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); } // 添加环境变量 add_environment("PATH", _PATH_DEFPATH); // 获取本次启动是否是系统启动的第一阶段,如果是第一阶段, // 则进入下面的if语句中,创建并挂载相关的文件系统。 bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr); //创建文件并挂载 if (is_first_stage) { boot_clock::time_point start_time = boot_clock::now(); // Clear the umask. umask(0); // Get the basic filesystem setup we need put together in the initramdisk // on / and then we'll let the rc file figure out the rest. // 创建和挂载启动所需的文件目录 mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); #define MAKE_STR(x) __STRING(x) mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)); // Don't expose the raw commandline to unprivileged processes. chmod("/proc/cmdline", 0440); gid_t groups[] = { AID_READPROC }; setgroups(arraysize(groups), groups); mount("sysfs", "/sys", "sysfs", 0, NULL); mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL); mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)); mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)); mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)); // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually // talk to the outside world... // 初始化Kernel的Log,这样就可以从外界获取Kernel的日志 InitKernelLogging(argv); LOG(INFO)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3